package com.sc.nft.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.DaoPledgeDigitDTO;
import com.sc.nft.entity.req.DaoPledgeCreateRequest;
import com.sc.nft.entity.req.DaoPledgePeriodsCreateRequest;
import com.sc.nft.entity.req.DaoPledgeProduceCreateRequest;
import com.sc.nft.entity.req.DaoPledgeUpdateRequest;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.DaoPledgeService;
import com.sc.nft.service.UserConsensusService;
import com.sc.nft.service.UserEquityPropsService;
import com.sc.nft.util.LocalDateTimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * dao质押活动表服务接口实现
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DaoPledgeServiceImpl implements DaoPledgeService {

    private final DaoPledgeDao daoPledgeDao;
    private final DaoPledgePeriodsDao daoPledgePeriodsDao;
    private final DaoPledgeProduceDao daoPledgeProduceDao;
    private final DaoPledgeUserPeriodsDao daoPledgeUserPeriodsDao;
    private final DaoPledgeUserProduceDao daoPledgeUserProduceDao;
    private final DaoPledgeRewardPeriodsDao daoPledgeRewardPeriodsDao;
    private final DaoPledgeRewardProduceDao daoPledgeRewardProduceDao;
    private final UserCollectionDao userCollectionDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final ExitConsensusUserDao exitConsensusUserDao;
    private final UserConsensusService userConsensusService;
    private final DaoPledgeDigitalDao daoPledgeDigitalDao;
    private final EquityPropsDao equityPropsDao;
    private final UserInfoDao userInfoDao;
    private final DaoPledgeDirectPushDao daoPledgeDirectPushDao;
    private final StaticDataDao staticDataDao;
    private final UserEquityPropsService userEquityPropsService;
    private final UserCollectionChainLogDao userCollectionChainLogDao;
    private final UserChainInfoDao userChainInfoDao;
    private final UserRelevanceDao userRelevanceDao;

    private DaoPledgeStatusEnum setPledgeStatus(Integer rewardBatch, Long pledgeId) {
        Integer produceCount = daoPledgeProduceDao.countPledgeBatch(pledgeId);
        if (rewardBatch < produceCount) {
            return DaoPledgeStatusEnum.IN;
        } else {
            return DaoPledgeStatusEnum.END;
        }
    }


    private void assembleActiveStatus(DaoPledge daoPledge, DaoPledgePeriods daoPledgePeriods, DaoPledgeDetailVO daoPledgeDetailVO) {
        DaoPledgePeriods nextPeriods = daoPledgePeriodsDao.getNextPeriods(daoPledge.getId(), daoPledgePeriods.getEndTime());
        if (Objects.isNull(nextPeriods)) {
            long daysBetween = ChronoUnit.DAYS.between(LocalDateTime.now(), LocalDateTimeUtil.dateToLocalDateTime(daoPledgePeriods.getEndTime()));
            daoPledgeDetailVO.setActiveStatus("预计距活动结束还有" + daysBetween + "天");
            assembleActiveTime(daoPledgePeriods, daoPledgeDetailVO, null);
            return;
        }

        daoPledgeDetailVO.setNextPeriods(nextPeriods.getPeriods());
        assembleActiveTime(daoPledgePeriods, daoPledgeDetailVO, nextPeriods);
    }

    private static void assembleActiveTime(DaoPledgePeriods daoPledgePeriods, DaoPledgeDetailVO daoPledgeDetailVO, DaoPledgePeriods nextPeriods) {
        long daysBetween;
        if (daoPledgeDetailVO.getDaoPledgeStatus() == DaoPledgeStatusEnum.NOT_START) {
            daoPledgeDetailVO.setNextStartTime(daoPledgePeriods.getStartTime());
            daoPledgeDetailVO.setActiveStatus("开始时间" + LocalDateTimeUtil.dateToLocalDateTime(daoPledgePeriods.getStartTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }
        if (Objects.isNull(nextPeriods)) {
            return;
        }
        if (daoPledgeDetailVO.getDaoPledgeStatus() == DaoPledgeStatusEnum.IN) {
            daoPledgeDetailVO.setNextStartTime(nextPeriods.getStartTime());
            daysBetween = ChronoUnit.DAYS.between(LocalDateTime.now(), LocalDateTimeUtil.dateToLocalDateTime(nextPeriods.getStartTime()));
            daoPledgeDetailVO.setActiveStatus("预计距下个自然发行期还有" + daysBetween + "天");
        } else if (daoPledgeDetailVO.getDaoPledgeStatus() == DaoPledgeStatusEnum.SETTLE) {
            daoPledgeDetailVO.setNextStartTime(nextPeriods.getStartTime());
            daysBetween = ChronoUnit.DAYS.between(LocalDateTime.now(), LocalDateTimeUtil.dateToLocalDateTime(nextPeriods.getStartTime()));
            daoPledgeDetailVO.setActiveStatus("预计距下个自然发行期还有" + daysBetween + "天");
        } else if (daoPledgeDetailVO.getDaoPledgeStatus() == DaoPledgeStatusEnum.END) {
            daoPledgeDetailVO.setNextStartTime(nextPeriods.getStartTime());
            daysBetween = ChronoUnit.DAYS.between(LocalDateTime.now(), LocalDateTimeUtil.dateToLocalDateTime(nextPeriods.getStartTime()));
            daoPledgeDetailVO.setActiveStatus("预计距下个自然发行期还有" + daysBetween + "天");
        }
    }

    private UserCollectionChainLog getUserCollectionChainLog(UserCollection userCollection, UserCollectionChainLog formUserChainLogInfo, UserChainInfo userChainInfo) {
        UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
        userCollectionChainLog.setUserId(userCollection.getUserId());
        userCollectionChainLog.setDaoId(0L);
        userCollectionChainLog.setUserCollectionId(userCollection.getId());
        userCollectionChainLog.setCollectionType(ReceivedCollectionType.PLEDGE_DESTROY);
        userCollectionChainLog.setType(UserChainTypeEnum.PlEDGE_DESTROY);
        userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
        userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
        userCollectionChainLog.setContractAddress(formUserChainLogInfo.getContractAddress());
        userCollectionChainLog.setDeployTransactionHash(formUserChainLogInfo.getTransactionHash());
        userCollectionChainLog.setProductId(formUserChainLogInfo.getProductId());
        userCollectionChainLog.setAddress(formUserChainLogInfo.getAddress());
        userCollectionChainLog.setTokenId(formUserChainLogInfo.getTokenId());
        userCollectionChainLog.setFromUserId(userCollection.getUserId());
        userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
        userCollectionChainLog.setFromUserAddress(formUserChainLogInfo.getToUserAddress());
        userCollectionChainLog.setToUserId(1L);
        userCollectionChainLog.setToUserCollectionId(0L);
        userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
        userCollectionChainLog.setCollectionChainId(0L);
        return userCollectionChainLog;
    }

    private DaoPledgeRewardProduce getDaoPledgeRewardProduce(Long periodsId, Integer currentBatch, DaoPledgeProduce daoPledgeProduce, Integer productNumber, Date grantTime) {
        DaoPledgeRewardProduce daoPledgeRewardProduce = new DaoPledgeRewardProduce();
        daoPledgeRewardProduce.setRewardPeriodsId(periodsId);
        daoPledgeRewardProduce.setBatch(currentBatch);
        daoPledgeRewardProduce.setPropId(daoPledgeProduce.getPropId());
        daoPledgeRewardProduce.setProductNumber(daoPledgeProduce.getProductNumber() * productNumber);
        daoPledgeRewardProduce.setGrantTime(grantTime);
        return daoPledgeRewardProduce;
    }

    private DaoPledgeRewardPeriods getDaoPledgeRewardPeriods(Long pledgeId, Long daoId, Integer periods, DaoPledgeUserPeriods daoPledgeUserPeriod) {
        DaoPledgeRewardPeriods daoPledgeRewardPeriods = new DaoPledgeRewardPeriods();
        daoPledgeRewardPeriods.setPledgeId(pledgeId);
        daoPledgeRewardPeriods.setUserId(daoPledgeUserPeriod.getUserId());
        daoPledgeRewardPeriods.setGrantTime(new Date());
        daoPledgeRewardPeriods.setUserPeriodsId(daoPledgeUserPeriod.getId());
        daoPledgeRewardPeriods.setPeriods(periods);
        daoPledgeRewardPeriods.setDaoId(daoId);
        return daoPledgeRewardPeriods;
    }

    private void settle(Long pledgeId, Integer currentPledgeNumber, int currentSum, DaoPledgePeriods periods, DaoPledge daoPledge, Date date) {
        if (currentPledgeNumber + currentSum < periods.getPledgeTotal()) {
            return;
        }

        LocalDateTime settleTime = LocalDateTimeUtil.dateToLocalDateTime(date);
        LocalDateTime upTime = settleTime.plusHours(1);

        periods.setFirstSettleTimeStart(LocalDateTimeUtil.localDateTimeToDate(settleTime));
        periods.setEndTime(LocalDateTimeUtil.localDateTimeToDate(upTime));

        if (!daoPledgePeriodsDao.updateById(periods)) {
            throw new GlobalRunTimeException(periods.getPeriods() + "期更新失败!请重试");
        }

        List<DaoPledgeUserPeriods> daoPledgeUserPeriods = daoPledgeUserPeriodsDao.listByPledgeIdAndStatus(pledgeId);
        List<Long> ids = daoPledgeUserPeriods.stream().map(DaoPledgeUserPeriods::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            Integer i = daoPledgeUserPeriodsDao.updateSettleTime(ids, date);
            if (i != ids.size()) {
                throw new GlobalRunTimeException("质押失败,结算时间更新错误!请重试");
            }
        }

        List<DaoPledgePeriods> daoPledgePeriods = daoPledgePeriodsDao.afterPeriods(pledgeId, periods.getPeriods());
        for (DaoPledgePeriods daoPledgePeriod : daoPledgePeriods) {
            daoPledgePeriod.setStartTime(LocalDateTimeUtil.localDateTimeToDate(upTime));
            LocalDateTime current = upTime.plusDays(daoPledgePeriod.getSettleDay());
            daoPledgePeriod.setFirstSettleTimeStart(LocalDateTimeUtil.localDateTimeToDate(current));
            LocalDateTime endTime = current.plusHours(1);
            daoPledgePeriod.setEndTime(LocalDateTimeUtil.localDateTimeToDate(endTime));
            daoPledge.setEndTime(LocalDateTimeUtil.localDateTimeToDate(endTime));
            upTime = current.plusHours(1);

            if (!daoPledgePeriodsDao.updateById(daoPledgePeriod)) {
                throw new GlobalRunTimeException(daoPledgePeriod.getPeriods() + "期更新失败!请重试");
            }
        }

        if (CollectionUtils.isEmpty(daoPledgePeriods)) {
            daoPledge.setEndTime(LocalDateTimeUtil.localDateTimeToDate(upTime));
        }

        if (!daoPledgeDao.updateById(daoPledge)) {
            throw new GlobalRunTimeException(daoPledge.getName() + "活动更新失败!请重试");
        }
    }

    /**
     * 扣减共识度
     *
     * @param consumeConsensus 活动
     * @param userId           userId
     * @param collections      质押藏品
     */
    private void deductionConsensus(Boolean consumeConsensus, Long userId, List<DaoPledgeDigitDTO> collections) {
        if (!consumeConsensus) {
            return;
        }
        //是否退出共识区
        ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(userId);
        if (Objects.nonNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
            return;
        }
        for (DaoPledgeDigitDTO collection : collections) {
            DigitalCollection digitalCollection = digitalCollectionDao.getById(collection.getCollectionId());
            if (digitalCollection.getCollectionType() != DigitalMarketTypeEnum.ECOLOGY) {
                continue;
            }
            userConsensusService.adjustConsensusService(userId, collection.getCollectionId(), (new BigDecimal(collection.getSize())).negate(), UserConsensusTypeEnums.PLEDGE_SELL, digitalCollection.getFirstTitle(), null);

        }

    }

    /**
     * 校验持有数量
     *
     * @param collections 质押藏品
     * @return 质押总数
     */
    private int checkHoldNumber(List<DaoPledgeDigitDTO> collections, Long userId) {
        int currentSum = 0;
        for (DaoPledgeDigitDTO collection : collections) {
            Integer holdCount = userCollectionDao.getHoldByUserIdAndCollectionIdAndCount(userId, collection.getCollectionId());
            DigitalCollection digitalCollection = digitalCollectionDao.getById(collection.getCollectionId());
            if (holdCount < collection.getSize()) {
                throw new GlobalRunTimeException(digitalCollection.getFirstTitle() + "持有数量不足");
            }
            currentSum += collection.getSize();
        }
        return currentSum;
    }

    /**
     * 销毁藏品
     *
     * @param collections 质押藏品
     */
    private void destroyNft(List<DaoPledgeDigitDTO> collections, Long userId) {
        UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(1L);
        for (DaoPledgeDigitDTO collection : collections) {
            List<UserCollection> userCollections = userCollectionDao.getListByUserIdAndCollectionIdAndCount(userId, collection.getCollectionId(), collection.getSize());
            if (userCollections.size() != collection.getSize()) {
                throw new GlobalRunTimeException("质押销毁藏品数量不足" + collection.getCollectionId());
            }
            for (UserCollection userCollection : userCollections) {
                UserCollectionChainLog formUserChainLogInfo = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());
                UserCollectionChainLog userCollectionChainLog = getUserCollectionChainLog(userCollection, formUserChainLogInfo, userChainInfo);
                userCollectionChainLogDao.save(userCollectionChainLog);
                // 扣掉藏品总库存和可用库存
                Boolean subSumCount = digitalCollectionDao.subSumCount(userCollection.getCollectionId(), 1);
                if (!subSumCount) {
                    log.info("质押藏品库存扣减失败,藏品ID:{}", userCollection.getCollectionId());
                    throw new GlobalRunTimeException("藏品库存扣减失败");
                }
                userCollection.setStatus(ChainStatusEnum.OFFLINE);
                userCollection.setIsHold(Boolean.FALSE);
                userCollectionDao.updateById(userCollection);
            }
        }
    }


    /**
     * 校验期数质押是否满
     *
     * @param collections         质押藏品
     * @param currentPledgeNumber 当前质押数量
     * @param pledgeTotal         期数
     */
    private void checkPeriods(List<DaoPledgeDigitDTO> collections, Integer currentPledgeNumber, Integer pledgeTotal) {
        if (currentPledgeNumber >= pledgeTotal) {
            throw new GlobalRunTimeException("质押数量已满");
        }
        int submitSize = collections.stream().mapToInt(DaoPledgeDigitDTO::getSize).sum();
        if (submitSize + currentPledgeNumber > pledgeTotal) {
            throw new GlobalRunTimeException("质押数量超过剩余加速数量");
        }
    }


    /**
     * 获取当前共创总数
     *
     * @param pledgeId 共创id
     * @param periods  期数id
     * @return 共创总数
     */
    public Integer getCurrentPledgeNumber(Long pledgeId, Integer periods) {
        List<DaoPledgeUserPeriods> daoPledgeUserPeriods = daoPledgeUserPeriodsDao.listPeriodsByPeriods(pledgeId, periods);
        List<Long> userPeriodsIds = daoPledgeUserPeriods.stream().map(DaoPledgeUserPeriods::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(userPeriodsIds)) {
            return 0;
        }
        List<DaoPledgeUserProduce> daoPledgeUserProduces = daoPledgeUserProduceDao.listProduceByPeriodIds(userPeriodsIds);
        return daoPledgeUserProduces.stream().mapToInt(DaoPledgeUserProduce::getProductNumber).sum();
    }


    private List<DaoPledgeDetailRewardVO> assembleReward(Long pledgeId) {
        List<DaoPledgeProduce> daoPledgeProduces = daoPledgeProduceDao.listByPledgeId(pledgeId);
        List<DaoPledgeDetailRewardVO> daoPledgeDetailRewardVOs = Lists.newArrayList();
        Map<Long, Integer> pledgeProductCountMap = daoPledgeProduces.stream().collect(Collectors.groupingBy(DaoPledgeProduce::getPropId, Collectors.summingInt(DaoPledgeProduce::getProductNumber)));
        for (Map.Entry<Long, Integer> dpp : pledgeProductCountMap.entrySet()) {
            Long key = dpp.getKey();
            Integer value = dpp.getValue();
            DaoPledgeDetailRewardVO daoPledgeDetailRewardVO = new DaoPledgeDetailRewardVO();
            EquityProps equityProps = equityPropsDao.getById(key);
            daoPledgeDetailRewardVO.setName(equityProps.getFirstTitle());
            daoPledgeDetailRewardVO.setSize(value);
            daoPledgeDetailRewardVO.setCreationContent(equityProps.getCreationContent());
            daoPledgeDetailRewardVOs.add(daoPledgeDetailRewardVO);
        }

        return daoPledgeDetailRewardVOs;
    }

    private List<DaoPledgeConditionVO> assembleUserCondition(Long userId, Long pledgeId) {
        List<DaoPledgeDigital> daoPledgeDigital = daoPledgeDigitalDao.listByPledgeId(pledgeId);
        List<DaoPledgeConditionVO> list = new ArrayList<>();
        for (DaoPledgeDigital pledgeDigital : daoPledgeDigital) {
            DigitalCollection digitalCollection = digitalCollectionDao.getById(pledgeDigital.getCollectionId());
            DaoPledgeConditionVO daoPledgeConditionVO = new DaoPledgeConditionVO();
            daoPledgeConditionVO.setName(digitalCollection.getFirstTitle());
            daoPledgeConditionVO.setCreationContent(digitalCollection.getCreationContent());
            daoPledgeConditionVO.setCollectionId(digitalCollection.getId());
            Integer holdCountByCollectionId = userCollectionDao.getHoldByUserIdAndCollectionIdAndCount(userId, digitalCollection.getId());
            daoPledgeConditionVO.setHoldCount(holdCountByCollectionId);
            list.add(daoPledgeConditionVO);
        }
        return list;
    }

    private static void assemblePledgeStatus(DaoPledgeDetailVO daoPledgeDetailVO, DaoPledgePeriods daoPledgePeriods) {
        daoPledgeDetailVO.setDaoPledgeStatus(DaoPledgeStatusEnum.END);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = LocalDateTimeUtil.dateToLocalDateTime(daoPledgePeriods.getStartTime());
        LocalDateTime endTime = LocalDateTimeUtil.dateToLocalDateTime(daoPledgePeriods.getEndTime());
        LocalDateTime firstSettleTime = LocalDateTimeUtil.dateToLocalDateTime(daoPledgePeriods.getFirstSettleTimeStart());
        if (now.isBefore(startTime)) {
            daoPledgeDetailVO.setDaoPledgeStatus(DaoPledgeStatusEnum.NOT_START);
            daoPledgeDetailVO.setDaoPledgeStatusStr(DaoPledgeStatusEnum.NOT_START.getDescription());
        }
        if (now.isAfter(startTime) && now.isBefore(firstSettleTime)) {
            daoPledgeDetailVO.setDaoPledgeStatus(DaoPledgeStatusEnum.IN);
            daoPledgeDetailVO.setDaoPledgeStatusStr(DaoPledgeStatusEnum.IN.getDescription());
        }
        if (now.isAfter(firstSettleTime) && now.isBefore(endTime)) {
            daoPledgeDetailVO.setDaoPledgeStatus(DaoPledgeStatusEnum.SETTLE);
            daoPledgeDetailVO.setDaoPledgeStatusStr(DaoPledgeStatusEnum.SETTLE.getDescription());
        }
    }


    @Override
    public DaoPledgeDetailVO detailPledge(Long id, Long userId) {
        DaoPledge daoPledge = daoPledgeDao.getById(id);
        if (Objects.isNull(daoPledge)) {
            throw new GlobalRunTimeException("质押活动不存在!");
        }
        DaoPledgePeriods daoPledgePeriods = daoPledgePeriodsDao.getCurrentPeriods(daoPledge.getId());
        if (Objects.isNull(daoPledgePeriods)) {
            List<DaoPledgePeriods> daoPledgePeriodsList = daoPledgePeriodsDao.listByPledgeId(daoPledge.getId());
            if (!CollectionUtils.isEmpty(daoPledgePeriodsList)) {
                daoPledgePeriods = daoPledgePeriodsList.get(daoPledgePeriodsList.size() - 1);
            }
        }

        Integer batchCount = daoPledgeProduceDao.countPledgeBatch(daoPledge.getId());

        DaoPledgeDetailVO daoPledgeDetailVO = new DaoPledgeDetailVO();
        daoPledgeDetailVO.setId(daoPledge.getId());
        daoPledgeDetailVO.setPeriodsId(daoPledgePeriods.getId());
        daoPledgeDetailVO.setName(daoPledge.getName());
        daoPledgeDetailVO.setCoverPicture(daoPledge.getMasterPicture());
        daoPledgeDetailVO.setCurrentPeriods(daoPledgePeriods.getPeriods());
        daoPledgeDetailVO.setPeriods(batchCount);
        daoPledgeDetailVO.setCurrentPledgeTotal(daoPledgePeriods.getPledgeTotal());
        daoPledgeDetailVO.setRewards(assembleReward(daoPledge.getId()));
        daoPledgeDetailVO.setCondition(assembleUserCondition(userId, daoPledge.getId()));
        daoPledgeDetailVO.setActiveRule(daoPledge.getActiveRule());
        //获取当前质押期数
        Integer currentPledgeNumber = getCurrentPledgeNumber(daoPledge.getId(), daoPledgePeriods.getPeriods());
        daoPledgeDetailVO.setPledgeTotal(daoPledgePeriods.getPledgeTotal() - currentPledgeNumber);
        //组装质押状态
        assemblePledgeStatus(daoPledgeDetailVO, daoPledgePeriods);
        //获取下个发行期
        assembleActiveStatus(daoPledge, daoPledgePeriods, daoPledgeDetailVO);
        return daoPledgeDetailVO;
    }


    @Override
    public IPage<DaoPledgePageVO> pagePledge(Long daoId, Integer pageNo, Integer pageSize) {
        Page<DaoPledge> daoPledgePage = daoPledgeDao.pagePledge(new Page<>(pageNo, pageSize), daoId);
        return daoPledgePage.convert(x -> {
            DaoPledgePeriods currentPeriods = daoPledgePeriodsDao.getCurrentPeriods(x.getId());
            DaoPledgePageVO daoPledgePageVO = new DaoPledgePageVO();
            daoPledgePageVO.setId(x.getId());
            daoPledgePageVO.setName(x.getName());
            daoPledgePageVO.setCoverPicture(x.getCoverPicture());
            if (Objects.nonNull(currentPeriods)) {
                daoPledgePageVO.setStartTime(currentPeriods.getStartTime());
                daoPledgePageVO.setPeriods(currentPeriods.getPeriods());
                if (currentPeriods.getStartTime().before(new Date())) {
                    daoPledgePageVO.setDaoPledgeStatus(DaoPledgeStatusEnum.IN);
                    daoPledgePageVO.setActiveStatus(DaoPledgeStatusEnum.IN.getDescription());
                } else {
                    daoPledgePageVO.setActiveStatus(LocalDateTimeUtil.dateToLocalDateTime(currentPeriods.getStartTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                }
            } else {
                daoPledgePageVO.setDaoPledgeStatus(DaoPledgeStatusEnum.END);
                daoPledgePageVO.setActiveStatus(DaoPledgeStatusEnum.END.getDescription());
            }
            return daoPledgePageVO;
        });
    }

    @Override
    public IPage<DaoPledgeRecordVO> pagePledgeRecord(Long daoId, Integer pageNo, Integer pageSize, Long userId) {
        Page<DaoPledgeUserPeriods> daoPledgeUserPeriodsPage = daoPledgeUserPeriodsDao.pagePeriodsByUserId(new Page<>(pageNo, pageSize), userId, daoId);
        return daoPledgeUserPeriodsPage.convert(x -> {
            DaoPledgeRecordVO daoPledgePageVO = new DaoPledgeRecordVO();
            DaoPledge daoPledge = daoPledgeDao.getById(x.getPledgeId());
            daoPledgePageVO.setId(x.getId());
            daoPledgePageVO.setTitle(daoPledge.getName() + "·" + x.getPeriods() + "期");
            daoPledgePageVO.setCoverPicture(daoPledge.getCoverPicture());
            daoPledgePageVO.setCreateTime(x.getCreateTime());
            List<DaoPledgeUserProduce> daoPledgeUserProduces = daoPledgeUserProduceDao.listByUserPeriodsId(x.getId());
            if (!CollectionUtils.isEmpty(daoPledgeUserProduces)) {
                Map<Long, Integer> resultMap = daoPledgeUserProduces.stream().collect(Collectors.groupingBy(DaoPledgeUserProduce::getCollectionId, Collectors.reducing(0, DaoPledgeUserProduce::getProductNumber, Integer::sum)));
                StringJoiner joiner = new StringJoiner("、");
                for (Map.Entry<Long, Integer> product : resultMap.entrySet()) {
                    Long key = product.getKey();
                    Integer value = product.getValue();
                    DigitalCollection digitalCollection = this.digitalCollectionDao.getById(key);
                    if (Objects.nonNull(digitalCollection)) {
                        joiner.add(digitalCollection.getFirstTitle() + "*" + value);
                    }
                }
                daoPledgePageVO.setPledgeCount(joiner.toString());
            }
            DaoPledgeStatusEnum daoPledgeStatusEnum = setPledgeStatus(x.getRewardBatch(), x.getPledgeId());
            daoPledgePageVO.setDaoPledgeStatus(daoPledgeStatusEnum);
            daoPledgePageVO.setDaoPledgeStatusStr(daoPledgeStatusEnum.getDescription());
            return daoPledgePageVO;
        });
    }

    @Override
    public DaoPledgeRecordDetailVO detailPledgeRecord(Long userId, Long id) {
        DaoPledgeUserPeriods daoPledgeUserPeriods = daoPledgeUserPeriodsDao.getById(id);
        DaoPledgeRecordDetailVO daoPledgeRecordDetailVO = new DaoPledgeRecordDetailVO();
        DaoPledgeStatusEnum daoPledgeStatusEnum = setPledgeStatus(daoPledgeUserPeriods.getRewardBatch(), daoPledgeUserPeriods.getPledgeId());
        daoPledgeRecordDetailVO.setDaoPledgeStatus(daoPledgeStatusEnum);
        daoPledgeRecordDetailVO.setDaoPledgeStatusStr(daoPledgeStatusEnum.getDescription());
        daoPledgeRecordDetailVO.setStartTime(daoPledgeUserPeriods.getCreateTime());
        daoPledgeRecordDetailVO.setProductCount(daoPledgeUserPeriods.getRewardBatch());
        if (!daoPledgeUserPeriods.getSettleStatus()) {
            daoPledgeRecordDetailVO.setNextTime(daoPledgeUserPeriods.getSettleTime());
        }

        List<DaoPledgeUserProduce> daoPledgeUserProduces = daoPledgeUserProduceDao.listByUserPeriodsId(daoPledgeUserPeriods.getId());
        List<DaoPledgeDigitVO> daoPledgeDigitVOs = new ArrayList<>();
        for (DaoPledgeUserProduce daoPledgeUserProduce : daoPledgeUserProduces) {
            DigitalCollection digitalCollection = digitalCollectionDao.getById(daoPledgeUserProduce.getCollectionId());
            DaoPledgeDigitVO daoPledgeDigitVO = new DaoPledgeDigitVO();
            daoPledgeDigitVO.setName(digitalCollection.getFirstTitle());
            daoPledgeDigitVO.setSize(daoPledgeUserProduce.getProductNumber());
            daoPledgeDigitVO.setCreationContent(digitalCollection.getCreationContent());
            daoPledgeDigitVOs.add(daoPledgeDigitVO);
        }
        daoPledgeRecordDetailVO.setDigits(daoPledgeDigitVOs);

        List<DaoPledgeRewardPeriods> daoPledgeRewardPeriods = daoPledgeRewardPeriodsDao.listByUserPeriodsId(daoPledgeUserPeriods.getId());
        List<Long> ids = daoPledgeRewardPeriods.stream().map(DaoPledgeRewardPeriods::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<DaoPledgeBatchVO> batchList = new ArrayList<>();
            List<DaoPledgeRewardProduce> daoPledgeRewardProduces = daoPledgeRewardProduceDao.listByRewardPeriodsId(ids);
            for (DaoPledgeRewardProduce daoPledgeRewardProduce : daoPledgeRewardProduces) {
                DaoPledgeBatchVO daoPledgeBatchVO = new DaoPledgeBatchVO();
                daoPledgeBatchVO.setBatch("产出批次：第" + daoPledgeRewardProduce.getBatch() + "次");
                daoPledgeBatchVO.setCreateTime(daoPledgeRewardProduce.getGrantTime());
                EquityProps equityProps = equityPropsDao.getById(daoPledgeRewardProduce.getPropId());
                daoPledgeBatchVO.setName(equityProps.getFirstTitle() + " * " + daoPledgeRewardProduce.getProductNumber());
                batchList.add(daoPledgeBatchVO);
            }
            daoPledgeRecordDetailVO.setBatch(batchList);
        }
        return daoPledgeRecordDetailVO;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settlePledge() {
        Date grantTime = new Date();

        List<DaoPledgeUserPeriods> dps = daoPledgeUserPeriodsDao.listWaitSettle(new Date());
        for (DaoPledgeUserPeriods daoPledgeUserPeriod : dps) {
            DaoPledge daoPledge = daoPledgeDao.getById(daoPledgeUserPeriod.getPledgeId());
            if (Objects.isNull(daoPledge)) {
                continue;
            }

            Integer batchCount = daoPledgeProduceDao.countPledgeBatch(daoPledge.getId());//总批次
            DaoPledgePeriods periods = daoPledgePeriodsDao.getPledgeIdAndPeriods(daoPledge.getId(), daoPledgeUserPeriod.getPeriods());
            if (Objects.isNull(periods)) {
                continue;
            }

            Integer currentBatch = daoPledgeUserPeriod.getRewardBatch() + 1;
            DaoPledgeProduce daoPledgeProduce = daoPledgeProduceDao.getPledgeBatch(daoPledgeUserPeriod.getPledgeId(), currentBatch);
            Integer productNumber = daoPledgeUserProduceDao.sumProductNumber(daoPledgeUserPeriod.getId());

            DaoPledgeRewardPeriods daoPledgeRewardPeriods = getDaoPledgeRewardPeriods(daoPledge.getId(), daoPledge.getDaoId(), daoPledgeUserPeriod.getPeriods(), daoPledgeUserPeriod);
            daoPledgeRewardPeriodsDao.save(daoPledgeRewardPeriods);

            DaoPledgeRewardProduce daoPledgeRewardProduce = getDaoPledgeRewardProduce(daoPledgeRewardPeriods.getId(), currentBatch, daoPledgeProduce, productNumber, grantTime);
            daoPledgeRewardProduceDao.save(daoPledgeRewardProduce);

            EquityProps equityProps = equityPropsDao.getById(daoPledgeProduce.getPropId());
            userEquityPropsService.addEquityPropsByUser(equityProps, daoPledgeUserPeriod.getUserId(), UserEquityPropsGetTypeEnum.DAO_PLEDGE, daoPledgeProduce.getProductNumber() * productNumber, daoPledge.getName(), daoPledgeUserPeriod.getId(),
                    BigDecimal.ZERO, UserEquityPropsGetTypeEnum.DAO_PLEDGE, daoPledgeUserPeriod.getId());

            //直推奖励
            directPush(daoPledge, daoPledgeUserPeriod.getPeriods(), daoPledgeUserPeriod, daoPledgeProduce, productNumber, equityProps, currentBatch, grantTime);

            daoPledgeUserPeriod.setRewardBatch(currentBatch);
            LocalDateTime nextTimeLocal = LocalDateTimeUtil.dateToLocalDateTime(daoPledgeUserPeriod.getSettleTime()).plusDays(periods.getSettleDay());
            daoPledgeUserPeriod.setSettleTime(LocalDateTimeUtil.localDateTimeToDate(nextTimeLocal));
            if (currentBatch >= batchCount) {
                daoPledgeUserPeriod.setSettleStatus(Boolean.TRUE);
            }

            daoPledgeUserPeriodsDao.updateById(daoPledgeUserPeriod);
        }

    }

    private void directPush(DaoPledge daoPledge, Integer periods, DaoPledgeUserPeriods daoPledgeUserPeriod, DaoPledgeProduce daoPledgeProduce, Integer productNumber, EquityProps equityProps, Integer currentBatch, Date grantTime) {
        BigDecimal pushRatio = daoPledge.getPushRatio();
        if (pushRatio.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        BigDecimal size = new BigDecimal(daoPledgeProduce.getProductNumber() * productNumber);
        BigDecimal divide = size.multiply(pushRatio).setScale(0, RoundingMode.DOWN);
        UserRelevance userRelevance = userRelevanceDao.getByRelevanceIdAndLv(daoPledgeUserPeriod.getUserId(), 1);
        if (Objects.isNull(userRelevance) || divide.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        userEquityPropsService.addEquityPropsByUser(equityProps, userRelevance.getUserId(), UserEquityPropsGetTypeEnum.DAO_PLEDGE, divide.intValue(), daoPledge.getName(), daoPledgeUserPeriod.getId(),
                BigDecimal.ZERO, UserEquityPropsGetTypeEnum.DAO_PLEDGE, daoPledgeUserPeriod.getId());

        //保存直推奖励记录
        DaoPledgeDirectPush daoPledgeDirectPush = new DaoPledgeDirectPush();
        daoPledgeDirectPush.setDaoId(daoPledge.getDaoId());
        daoPledgeDirectPush.setPledgeId(daoPledge.getId());
        daoPledgeDirectPush.setPeriods(periods);
        daoPledgeDirectPush.setBatch(currentBatch);
        daoPledgeDirectPush.setTargetUserId(daoPledgeUserPeriod.getUserId());
        daoPledgeDirectPush.setSourceUserId(userRelevance.getUserId());
        daoPledgeDirectPush.setPropId(daoPledgeProduce.getPropId());
        List<DaoPledgeProduce> daoPledgeProduces = daoPledgeProduceDao.listPledgeProduce(daoPledge.getId());
        if (!CollectionUtils.isEmpty(daoPledgeProduces)) {
            daoPledgeDirectPush.setTotalOutCount(daoPledgeProduces.stream().mapToInt(DaoPledgeProduce::getProductNumber).sum());
        }
        daoPledgeDirectPush.setRewardCount(divide.intValue());
        daoPledgeDirectPush.setGrantTime(grantTime);

        if (!daoPledgeDirectPushDao.save(daoPledgeDirectPush)) {
            throw new GlobalRunTimeException("直推奖励记录保存失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pledge(Long userId, Long daoId, Long pledgeId, Long periodsId, List<DaoPledgeDigitDTO> collections) {
        DaoPledge daoPledge = daoPledgeDao.getById(pledgeId);
        //校验质押状态
        isPledgeConditions(userId, daoId, pledgeId, periodsId, collections);

        //获取当前期数
        DaoPledgePeriods periods = daoPledgePeriodsDao.getById(periodsId);

        //获取当前质押总数
        Integer currentPledgeNumber = getCurrentPledgeNumber(pledgeId, periods.getPeriods());

        //校验期数质押是否满
        checkPeriods(collections, currentPledgeNumber, periods.getPledgeTotal());

        //校验持有数量
        int currentSum = checkHoldNumber(collections, userId);
        //销毁nft
        destroyNft(collections, userId);
        //扣减共识度
        deductionConsensus(daoPledge.getConsumeConsensus(), userId, collections);

        LocalDateTime now = LocalDateTime.now();
        Date currentDate = LocalDateTimeUtil.localDateTimeToDate(now.plusDays(periods.getSettleDay()));
        Date nowDate = LocalDateTimeUtil.localDateTimeToDate(now);

        DaoPledgeUserPeriods saveUserPeriods = new DaoPledgeUserPeriods();
        saveUserPeriods.setPledgeId(pledgeId);
        saveUserPeriods.setUserId(userId);
        saveUserPeriods.setDaoId(daoId);
        saveUserPeriods.setPeriods(periods.getPeriods());
        saveUserPeriods.setSettleTime(currentDate);
        saveUserPeriods.setCreateTime(nowDate);
        if (!daoPledgeUserPeriodsDao.save(saveUserPeriods)) {
            throw new GlobalRunTimeException("用户质押期数记录保存失败!");
        }

        List<DaoPledgeUserProduce> saveUserProduces = new ArrayList<>();
        for (DaoPledgeDigitDTO collection : collections) {
            DaoPledgeUserProduce saveUserProduce = new DaoPledgeUserProduce();
            saveUserProduce.setUserId(userId);
            saveUserProduce.setPledgeId(pledgeId);
            saveUserProduce.setUserPeriodsId(saveUserPeriods.getId());
            saveUserProduce.setPeriods(periods.getPeriods());
            saveUserProduce.setCollectionId(collection.getCollectionId());
            saveUserProduce.setProductNumber(collection.getSize());
            saveUserProduces.add(saveUserProduce);
        }
        Integer saveSize = daoPledgeUserProduceDao.saveBatch(saveUserProduces);
        if (saveUserProduces.size() != saveSize) {
            throw new GlobalRunTimeException("用户质押产品记录保存失败!");
        }

        //如果质押满了 那就直接结算
        settle(pledgeId, currentPledgeNumber, currentSum, periods, daoPledge, nowDate);
    }


    @Override
    public Boolean isPledgeConditions(Long userId, Long daoId, Long pledgeId, Long periodsId, List<DaoPledgeDigitDTO> collections) {
        DaoPledge daoPledge = daoPledgeDao.getById(pledgeId);
        if (Objects.isNull(daoPledge)) {
            throw new GlobalRunTimeException("质押活动不存在");
        }
        if (!daoPledge.getStatus()) {
            throw new GlobalRunTimeException("活动已下架，不可质押");
        }
        if (daoPledge.getStartTime().after(new Date())) {
            throw new GlobalRunTimeException("活动未开始");
        }

        int submitSize = collections.stream().mapToInt(DaoPledgeDigitDTO::getSize).sum();
        if (submitSize > 20) {
            throw new GlobalRunTimeException("单次质押总数不能超过20个");
        }
        return Boolean.TRUE;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(DaoPledgeCreateRequest request) {
        //校验
        validateCreate(request);
        //region 主表
        DaoPledge daoPledge = new DaoPledge();
        daoPledge.setDaoId(request.getDaoId());
        daoPledge.setName(request.getName());
        daoPledge.setCoverPicture(request.getCoverPicture());
        daoPledge.setMasterPicture(request.getMasterPicture());
        daoPledge.setStartTime(request.getStartTime());
        Date startTime = request.getStartTime();
        Date endTime = request.getStartTime();
        for (DaoPledgePeriodsCreateRequest daoPledgePeriodsCreateRequest : request.getPeriodsList()) {
            endTime = DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay());
            startTime = DateUtil.offsetHour(endTime, 1);
        }
        daoPledge.setEndTime(endTime);
        daoPledge.setStatus(Boolean.FALSE);
        daoPledge.setActiveRule(request.getActiveRule());
        daoPledge.setPushRatio(request.getPushRatio());
        daoPledge.setConsumeConsensus(request.getConsumeConsensus());
        daoPledge.setVersion(1);
        Assert.isTrue(daoPledgeDao.save(daoPledge), () -> new GlobalRunTimeException("保存失败"));
        //endregion
        //region 藏品
        for (Long collectionId : request.getCollectionIdList()) {
            DaoPledgeDigital daoPledgeDigital = new DaoPledgeDigital();
            daoPledgeDigital.setPledgeId(daoPledge.getId());
            daoPledgeDigital.setCollectionId(collectionId);
            Assert.isTrue(daoPledgeDigitalDao.save(daoPledgeDigital), () -> new GlobalRunTimeException("保存失败"));
        }
        //endregion
        //region 发行期
        startTime = request.getStartTime();
        for (DaoPledgePeriodsCreateRequest daoPledgePeriodsCreateRequest : request.getPeriodsList()) {
            DaoPledgePeriods daoPledgePeriods = new DaoPledgePeriods();
            daoPledgePeriods.setPledgeId(daoPledge.getId());
            daoPledgePeriods.setPeriods(daoPledgePeriodsCreateRequest.getPeriods());
            daoPledgePeriods.setPledgeTotal(daoPledgePeriodsCreateRequest.getPledgeTotal());
            daoPledgePeriods.setSettleDay(daoPledgePeriodsCreateRequest.getSettleDay());
            daoPledgePeriods.setVersion(1);
            daoPledgePeriods.setStartTime(startTime);
            daoPledgePeriods.setEndTime(DateUtil.offsetHour(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()), 1));
            daoPledgePeriods.setFirstSettleTimeStart(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()));
            Assert.isTrue(daoPledgePeriodsDao.save(daoPledgePeriods), () -> new GlobalRunTimeException("保存失败"));
            startTime = DateUtil.offsetHour(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()), 1);
        }
        //endregion
        //region 产出
        for (DaoPledgeProduceCreateRequest daoPledgeProduceCreateRequest : request.getProduceList()) {
            DaoPledgeProduce daoPledgeProduce = new DaoPledgeProduce();
            daoPledgeProduce.setPledgeId(daoPledge.getId());
            daoPledgeProduce.setBatch(daoPledgeProduceCreateRequest.getBatch());
            daoPledgeProduce.setPropId(daoPledgeProduceCreateRequest.getPropId());
            daoPledgeProduce.setProductNumber(daoPledgeProduceCreateRequest.getProductNumber());
            Assert.isTrue(daoPledgeProduceDao.save(daoPledgeProduce), () -> new GlobalRunTimeException("保存失败"));
        }
        //endregion
    }

    @Override
    public void update(DaoPledgeUpdateRequest request) {
        //校验
        DaoPledge daoPledge = validateUpdate(request);

        //修改绑定条件藏品
        updatePledgeDigital(request, daoPledge);

        //修改期数
        Date endTimeUp = updatePeriods(request, daoPledge);

        //修改产出的批次和道具
        updateProduce(request, daoPledge);

        if (daoPledge.getStatus()) {
            daoPledge.setEndTime(endTimeUp);
        } else {
            daoPledge.setName(request.getName());
            daoPledge.setCoverPicture(request.getCoverPicture());
            daoPledge.setMasterPicture(request.getMasterPicture());
            daoPledge.setStartTime(request.getStartTime());
            Date startTime = request.getStartTime();
            Date endTime = request.getStartTime();
            for (DaoPledgePeriodsCreateRequest daoPledgePeriodsCreateRequest : request.getPeriodsList()) {
                endTime = DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay());
                startTime = DateUtil.offsetHour(endTime, 1);
            }
            daoPledge.setEndTime(endTime);
            daoPledge.setActiveRule(request.getActiveRule());
            daoPledge.setPushRatio(request.getPushRatio());
            daoPledge.setConsumeConsensus(request.getConsumeConsensus());
        }
        Assert.isTrue(daoPledgeDao.updateById(daoPledge), () -> new GlobalRunTimeException("保存失败"));

    }

    private Date updatePeriods(DaoPledgeUpdateRequest request, DaoPledge daoPledge) {
        List<DaoPledgePeriods> daoPledgePeriodsList = daoPledgePeriodsDao.listByPledgeId(request.getId());

        Date startTime = request.getStartTime();
        Date endTime = new Date();
        if (!daoPledge.getStatus()) {
            List<Long> ids = daoPledgePeriodsList.stream().map(DaoPledgePeriods::getId).collect(Collectors.toList());
            Assert.isTrue(daoPledgePeriodsDao.removeByIds(ids), () -> new GlobalRunTimeException("老期数删除失败"));
        }

        if (!CollectionUtils.isEmpty(daoPledgePeriodsList)) {
            DaoPledgePeriods dpp = daoPledgePeriodsList.get(daoPledgePeriodsList.size() - 1);
            startTime = dpp.getEndTime();
        }


        for (DaoPledgePeriodsCreateRequest daoPledgePeriodsCreateRequest : request.getPeriodsList()) {
            if (!daoPledgePeriodsCreateRequest.getIsNewAdd() && daoPledge.getStatus()) {
                continue;
            }
            DaoPledgePeriods daoPledgePeriods = new DaoPledgePeriods();
            daoPledgePeriods.setPledgeId(daoPledge.getId());
            daoPledgePeriods.setPeriods(daoPledgePeriodsCreateRequest.getPeriods());
            daoPledgePeriods.setPledgeTotal(daoPledgePeriodsCreateRequest.getPledgeTotal());
            daoPledgePeriods.setSettleDay(daoPledgePeriodsCreateRequest.getSettleDay());
            daoPledgePeriods.setVersion(1);
            daoPledgePeriods.setStartTime(startTime);
            endTime = DateUtil.offsetHour(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()), 1);
            daoPledgePeriods.setEndTime(endTime);
            daoPledgePeriods.setFirstSettleTimeStart(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()));
            Assert.isTrue(daoPledgePeriodsDao.save(daoPledgePeriods), () -> new GlobalRunTimeException("保存失败"));
            startTime = DateUtil.offsetHour(DateUtil.offsetDay(startTime, daoPledgePeriodsCreateRequest.getSettleDay()), 1);
        }

        return endTime;
    }

    private void updateProduce(DaoPledgeUpdateRequest request, DaoPledge daoPledge) {
        if (daoPledge.getStatus()) {
            return;
        }
        List<DaoPledgeProduce> daoPledgeProduceList = daoPledgeProduceDao.listByPledgeId(request.getId());
        for (DaoPledgeProduce daoPledgeProduce : daoPledgeProduceList) {
            daoPledgeProduceDao.removeById(daoPledgeProduce.getId());
        }
        for (DaoPledgeProduceCreateRequest daoPledgeProduceCreateRequest : request.getProduceList()) {
            DaoPledgeProduce daoPledgeProduce = new DaoPledgeProduce();
            daoPledgeProduce.setPledgeId(daoPledge.getId());
            daoPledgeProduce.setBatch(daoPledgeProduceCreateRequest.getBatch());
            daoPledgeProduce.setPropId(daoPledgeProduceCreateRequest.getPropId());
            daoPledgeProduce.setProductNumber(daoPledgeProduceCreateRequest.getProductNumber());
            Assert.isTrue(daoPledgeProduceDao.save(daoPledgeProduce), () -> new GlobalRunTimeException("保存失败"));
        }
    }

    private void updatePledgeDigital(DaoPledgeUpdateRequest request, DaoPledge daoPledge) {
        if (daoPledge.getStatus()) {
            return;
        }
        List<DaoPledgeDigital> daoPledgeDigitalList = daoPledgeDigitalDao.listByPledgeId(request.getId());
        for (DaoPledgeDigital daoPledgeDigital : daoPledgeDigitalList) {
            daoPledgeDigitalDao.removeById(daoPledgeDigital.getId());
        }
        for (Long collectionId : request.getCollectionIdList()) {
            DaoPledgeDigital daoPledgeDigital = new DaoPledgeDigital();
            daoPledgeDigital.setPledgeId(daoPledge.getId());
            daoPledgeDigital.setCollectionId(collectionId);
            Assert.isTrue(daoPledgeDigitalDao.save(daoPledgeDigital), () -> new GlobalRunTimeException("保存失败"));
        }
    }

    @Override
    public void updateStatus(Long id, Boolean status) {
        DaoPledge daoPledge = daoPledgeDao.getById(id);
        Assert.notNull(daoPledge, () -> new GlobalRunTimeException("活动不存在"));
        if (Objects.equals(daoPledge.getStatus(), status)) {
            return;
        }
        DateTime now = DateTime.now();
        if (daoPledge.getStatus()
                && daoPledge.getStartTime().before(now)
                && daoPledge.getEndTime().after(now)) {
            throw new GlobalRunTimeException("活动已开始，不能下架");
        }
        daoPledge.setStatus(status);
        Assert.isTrue(daoPledgeDao.updateById(daoPledge), () -> new GlobalRunTimeException("更新失败"));
    }

    @Override
    public IPage<DaoPledgeCommercialVO> page(Page page, Long daoId, String name) {
        DateTime now = DateTime.now();
        return daoPledgeDao.page(page, daoId, name).convert(v -> {
            DaoPledgeCommercialVO daoPledgeCommercialVO = new DaoPledgeCommercialVO();
            daoPledgeCommercialVO.setId(v.getId());
            daoPledgeCommercialVO.setName(v.getName());
            daoPledgeCommercialVO.setCoverPicture(v.getCoverPicture());
            daoPledgeCommercialVO.setMasterPicture(v.getMasterPicture());
            daoPledgeCommercialVO.setStartTime(v.getStartTime());
            daoPledgeCommercialVO.setCreateTime(v.getCreateTime());
            daoPledgeCommercialVO.setStatus(v.getStatus());
            if (now.isBefore(v.getStartTime())) {
                daoPledgeCommercialVO.setCurrentStatus(DaoPledgeCurrentStatusEnum.NOT_START);
                daoPledgeCommercialVO.setCurrentStatusName(DaoPledgeCurrentStatusEnum.NOT_START.getDescription());
            } else if (now.isAfter(v.getEndTime())) {
                daoPledgeCommercialVO.setCurrentStatus(DaoPledgeCurrentStatusEnum.END);
                daoPledgeCommercialVO.setCurrentStatusName(DaoPledgeCurrentStatusEnum.END.getDescription());
            } else {
                daoPledgeCommercialVO.setCurrentStatus(DaoPledgeCurrentStatusEnum.START);
                daoPledgeCommercialVO.setCurrentStatusName(DaoPledgeCurrentStatusEnum.START.getDescription());
            }
            daoPledgeCommercialVO.setActiveRule(v.getActiveRule());
            return daoPledgeCommercialVO;
        });
    }

    @Override
    public DaoPledgeDetailCommercialVO detail(Long id) {
        DaoPledge daoPledge = daoPledgeDao.getById(id);
        Assert.notNull(daoPledge, () -> new GlobalRunTimeException("活动不存在"));
        DaoPledgeDetailCommercialVO daoPledgeDetailCommercialVO = new DaoPledgeDetailCommercialVO();
        daoPledgeDetailCommercialVO.setId(id);
        daoPledgeDetailCommercialVO.setName(daoPledge.getName());
        daoPledgeDetailCommercialVO.setCoverPicture(daoPledge.getCoverPicture());
        daoPledgeDetailCommercialVO.setMasterPicture(daoPledge.getMasterPicture());
        daoPledgeDetailCommercialVO.setStartTime(daoPledge.getStartTime());
        daoPledgeDetailCommercialVO.setStatus(daoPledge.getStatus());
        daoPledgeDetailCommercialVO.setActiveRule(daoPledge.getActiveRule());
        daoPledgeDetailCommercialVO.setPushRatio(daoPledge.getPushRatio());
        daoPledgeDetailCommercialVO.setConsumeConsensus(daoPledge.getConsumeConsensus());
        //region 藏品
        List<Long> collectionIdList = daoPledgeDigitalDao.listByPledgeId(id).stream().map(DaoPledgeDigital::getCollectionId).collect(Collectors.toList());
        List<DigitalCollection> digitalCollectionList = digitalCollectionDao.getByIds(collectionIdList);
        Map<Long, DigitalCollection> digitalCollectionMap = CollectionUtil.isNotEmpty(digitalCollectionList) ? digitalCollectionList.stream().collect(Collectors.toMap(DigitalCollection::getId, Function.identity())) : Maps.newHashMap();
        daoPledgeDetailCommercialVO.setCollectionList(collectionIdList.stream().map(collectionId -> {
            DigitalCollection digitalCollection = digitalCollectionMap.get(collectionId);
            DaoPledgeDetailCollectionCommercialVO detailCollectionCommercialVO = new DaoPledgeDetailCollectionCommercialVO();
            detailCollectionCommercialVO.setCollectionId(collectionId);
            detailCollectionCommercialVO.setCollectionName(Objects.nonNull(digitalCollection) ? digitalCollection.getFirstTitle() : "");
            return detailCollectionCommercialVO;
        }).collect(Collectors.toList()));
        //endregion
        //region 发行期
        daoPledgeDetailCommercialVO.setPeriodsList(daoPledgePeriodsDao.listByPledgeId(id).stream().map(daoPledgePeriods -> {
            DaoPledgeDetailPeriodsCommercialVO daoPledgeDetailPeriodsCommercialVO = new DaoPledgeDetailPeriodsCommercialVO();
            daoPledgeDetailPeriodsCommercialVO.setPeriods(daoPledgePeriods.getPeriods());
            daoPledgeDetailPeriodsCommercialVO.setPledgeTotal(daoPledgePeriods.getPledgeTotal());
            daoPledgeDetailPeriodsCommercialVO.setSettleDay(daoPledgePeriods.getSettleDay());
            return daoPledgeDetailPeriodsCommercialVO;
        }).collect(Collectors.toList()));
        //endregion
        //region 产出
        List<DaoPledgeProduce> daoPledgeProduceList = daoPledgeProduceDao.listByPledgeId(id);
        List<Long> propIdList = daoPledgeProduceList.stream().map(DaoPledgeProduce::getPropId).distinct().collect(Collectors.toList());
        List<EquityProps> equityPropsList = equityPropsDao.listByIds(propIdList);
        Map<Long, EquityProps> equityPropsMap = CollectionUtil.isNotEmpty(equityPropsList) ? equityPropsList.stream().collect(Collectors.toMap(EquityProps::getId, Function.identity())) : Maps.newHashMap();
        daoPledgeDetailCommercialVO.setProduceList(daoPledgeProduceList.stream().map(daoPledgeProduce -> {
            EquityProps equityProps = equityPropsMap.get(daoPledgeProduce.getPropId());
            DaoPledgeDetailProduceCommercialVO detailProduceCommercialVO = new DaoPledgeDetailProduceCommercialVO();
            detailProduceCommercialVO.setBatch(daoPledgeProduce.getBatch());
            detailProduceCommercialVO.setPropId(daoPledgeProduce.getPropId());
            detailProduceCommercialVO.setPropName(Objects.nonNull(equityProps) ? equityProps.getFirstTitle() : "");
            detailProduceCommercialVO.setProductNumber(daoPledgeProduce.getProductNumber());
            return detailProduceCommercialVO;
        }).collect(Collectors.toList()));
        //endregion
        return daoPledgeDetailCommercialVO;
    }

    @Override
    public IPage<DaoPledgeUserPeriodsVO> userPeriodsPage(Page page, Long daoId, String userTel, String name, Integer periods) {
        List<Long> pledgeIdList = null;
        Long userId = null;
        if (StrUtil.isNotBlank(userTel)) {
            UserInfo userInfo = userInfoDao.getByUserTel(userTel);
            if (Objects.isNull(userInfo)) {
                return page;
            }
            userId = userInfo.getId();
        }
        if (StrUtil.isNotBlank(name)) {
            List<DaoPledge> daoPledgeList = daoPledgeDao.listByDaoAndName(daoId, name);
            if (CollectionUtil.isEmpty(daoPledgeList)) {
                return page;
            }
            pledgeIdList = daoPledgeList.stream().map(DaoPledge::getId).collect(Collectors.toList());
        }
        IPage<DaoPledgeUserPeriods> daoPledgeUserPeriodsIPage = daoPledgeUserPeriodsDao.page(page, daoId, pledgeIdList, userId, periods);
        //region 用户
        List<Long> userIdList = CollectionUtil.isNotEmpty(daoPledgeUserPeriodsIPage.getRecords()) ? daoPledgeUserPeriodsIPage.getRecords().stream().map(DaoPledgeUserPeriods::getUserId).distinct().collect(Collectors.toList()) : Lists.newArrayList();
        List<UserInfo> userInfoList = CollectionUtil.isNotEmpty(userIdList) ? userInfoDao.getByIdList(userIdList) : Lists.newArrayList();
        Map<Long, UserInfo> userInfoMap = CollectionUtil.isNotEmpty(userInfoList) ? userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity())) : Maps.newHashMap();
        //endregion
        //region 活动
        pledgeIdList = CollectionUtil.isNotEmpty(daoPledgeUserPeriodsIPage.getRecords()) ? daoPledgeUserPeriodsIPage.getRecords().stream().map(DaoPledgeUserPeriods::getPledgeId).distinct().collect(Collectors.toList()) : Lists.newArrayList();
        List<DaoPledge> daoPledgeList = CollectionUtil.isNotEmpty(pledgeIdList) ? daoPledgeDao.listByIds(pledgeIdList) : Lists.newArrayList();
        Map<Long, DaoPledge> daoPledgeMap = CollectionUtil.isNotEmpty(daoPledgeList) ? daoPledgeList.stream().collect(Collectors.toMap(DaoPledge::getId, Function.identity())) : Maps.newHashMap();
        //endregion
        return daoPledgeUserPeriodsIPage.convert(v -> {
            DaoPledgeUserPeriodsVO daoPledgeUserPeriodsVO = new DaoPledgeUserPeriodsVO();
            daoPledgeUserPeriodsVO.setId(v.getId());
            daoPledgeUserPeriodsVO.setUserId(v.getUserId());
            UserInfo userInfo = userInfoMap.get(v.getUserId());
            daoPledgeUserPeriodsVO.setUserTel(Objects.nonNull(userInfo) ? DesensitizedUtil.mobilePhone(userInfo.getUserTel()) : "");
            daoPledgeUserPeriodsVO.setNickName(Objects.nonNull(userInfo) ? userInfo.getNickName() : "");
            daoPledgeUserPeriodsVO.setPledgeId(v.getPledgeId());
            DaoPledge daoPledge = daoPledgeMap.get(v.getPledgeId());
            daoPledgeUserPeriodsVO.setName(Objects.nonNull(daoPledge) ? daoPledge.getName() : "");
            daoPledgeUserPeriodsVO.setPeriods(v.getPeriods());
            daoPledgeUserPeriodsVO.setCreateTime(v.getCreateTime());
            return daoPledgeUserPeriodsVO;
        });
    }

    @Override
    public List<DaoPledgeUserPeriodsDetailVO> userPeriodsDetail(Long id) {
        List<DaoPledgeUserProduce> daoPledgeUserProduceList = daoPledgeUserProduceDao.listByUserPeriodsId(id);
        if (CollectionUtil.isEmpty(daoPledgeUserProduceList)) {
            return Collections.emptyList();
        }
        Map<Long, Integer> produceMap = daoPledgeUserProduceList.stream().collect(Collectors.groupingBy(DaoPledgeUserProduce::getCollectionId, Collectors.summingInt(DaoPledgeUserProduce::getProductNumber)));
        List<DigitalCollection> digitalCollectionList = digitalCollectionDao.getByIds(new ArrayList<>(produceMap.keySet()));
        Map<Long, DigitalCollection> digitalCollectionMap = CollectionUtil.isNotEmpty(digitalCollectionList) ? digitalCollectionList.stream().collect(Collectors.toMap(DigitalCollection::getId, Function.identity())) : Maps.newHashMap();
        List<DaoPledgeUserPeriodsDetailVO> daoPledgeUserPeriodsDetailVOList = Lists.newArrayList();
        produceMap.forEach((key, value) -> {
            DaoPledgeUserPeriodsDetailVO daoPledgeUserPeriodsDetailVO = new DaoPledgeUserPeriodsDetailVO();
            daoPledgeUserPeriodsDetailVO.setCollectionId(key);
            daoPledgeUserPeriodsDetailVO.setCollectionName(Objects.nonNull(digitalCollectionMap.get(key)) ? digitalCollectionMap.get(key).getFirstTitle() : "");
            daoPledgeUserPeriodsDetailVO.setProductNumber(value);
            daoPledgeUserPeriodsDetailVOList.add(daoPledgeUserPeriodsDetailVO);
        });
        return daoPledgeUserPeriodsDetailVOList;
    }

    @Override
    public IPage<DaoPledgeRewardPeriodsVO> rewardPeriodsPage(Page page, Long daoId, String userTel, String name, Integer periods) {
        List<Long> pledgeIdList = null;
        Long userId = null;
        if (StrUtil.isNotBlank(userTel)) {
            UserInfo userInfo = userInfoDao.getByUserTel(userTel);
            if (Objects.isNull(userInfo)) {
                return page;
            }
            userId = userInfo.getId();
        }
        if (StrUtil.isNotBlank(name)) {
            List<DaoPledge> daoPledgeList = daoPledgeDao.listByDaoAndName(daoId, name);
            if (CollectionUtil.isEmpty(daoPledgeList)) {
                return page;
            }
            pledgeIdList = daoPledgeList.stream().map(DaoPledge::getId).collect(Collectors.toList());
        }
        IPage<DaoPledgeRewardPeriods> daoPledgeRewardPeriodsIPage = daoPledgeRewardPeriodsDao.page(page, daoId, pledgeIdList, userId, periods);
        //region 用户
        List<Long> userIdList = CollectionUtil.isNotEmpty(daoPledgeRewardPeriodsIPage.getRecords()) ? daoPledgeRewardPeriodsIPage.getRecords().stream().map(DaoPledgeRewardPeriods::getUserId).distinct().collect(Collectors.toList()) : Lists.newArrayList();
        List<UserInfo> userInfoList = CollectionUtil.isNotEmpty(userIdList) ? userInfoDao.getByIdList(userIdList) : Lists.newArrayList();
        Map<Long, UserInfo> userInfoMap = CollectionUtil.isNotEmpty(userInfoList) ? userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity())) : Maps.newHashMap();
        //endregion
        //region 活动
        pledgeIdList = CollectionUtil.isNotEmpty(daoPledgeRewardPeriodsIPage.getRecords()) ? daoPledgeRewardPeriodsIPage.getRecords().stream().map(DaoPledgeRewardPeriods::getPledgeId).distinct().collect(Collectors.toList()) : Lists.newArrayList();
        List<DaoPledge> daoPledgeList = CollectionUtil.isNotEmpty(pledgeIdList) ? daoPledgeDao.listByIds(pledgeIdList) : Lists.newArrayList();
        Map<Long, DaoPledge> daoPledgeMap = CollectionUtil.isNotEmpty(daoPledgeList) ? daoPledgeList.stream().collect(Collectors.toMap(DaoPledge::getId, Function.identity())) : Maps.newHashMap();
        //endregion
        return daoPledgeRewardPeriodsIPage.convert(v -> {
            DaoPledgeRewardPeriodsVO daoPledgeRewardPeriodsVO = new DaoPledgeRewardPeriodsVO();
            daoPledgeRewardPeriodsVO.setId(v.getId());
            daoPledgeRewardPeriodsVO.setUserId(v.getUserId());
            UserInfo userInfo = userInfoMap.get(v.getUserId());
            daoPledgeRewardPeriodsVO.setUserTel(Objects.nonNull(userInfo) ? DesensitizedUtil.mobilePhone(userInfo.getUserTel()) : "");
            daoPledgeRewardPeriodsVO.setNickName(Objects.nonNull(userInfo) ? userInfo.getNickName() : "");
            daoPledgeRewardPeriodsVO.setPledgeId(v.getPledgeId());
            DaoPledge daoPledge = daoPledgeMap.get(v.getPledgeId());
            daoPledgeRewardPeriodsVO.setName(Objects.nonNull(daoPledge) ? daoPledge.getName() : "");
            daoPledgeRewardPeriodsVO.setPeriods(v.getPeriods());
            daoPledgeRewardPeriodsVO.setGrantTime(v.getCreateTime());
            return daoPledgeRewardPeriodsVO;
        });
    }

    @Override
    public List<DaoPledgeRewardPeriodsDetailVO> rewardPeriodsDetail(Long id) {
        List<DaoPledgeRewardProduce> daoPledgeRewardProduceList = daoPledgeRewardProduceDao.listByRewardPeriodsId(Lists.newArrayList(id));
        if (CollectionUtil.isEmpty(daoPledgeRewardProduceList)) {
            return Collections.emptyList();
        }
        List<Long> propIdList = daoPledgeRewardProduceList.stream().map(DaoPledgeRewardProduce::getPropId).distinct().collect(Collectors.toList());
        List<EquityProps> equityPropsList = CollectionUtil.isNotEmpty(propIdList) ? equityPropsDao.listByIds(propIdList) : Lists.newArrayList();
        Map<Long, EquityProps> equityPropsMap = CollectionUtil.isNotEmpty(equityPropsList) ? equityPropsList.stream().collect(Collectors.toMap(EquityProps::getId, Function.identity())) : Maps.newHashMap();
        TreeMap<Integer, List<DaoPledgeRewardProduce>> daoPledgeRewardProduceMap = daoPledgeRewardProduceList.stream().collect(Collectors.groupingBy(DaoPledgeRewardProduce::getBatch, TreeMap::new, Collectors.toList()));
        List<DaoPledgeRewardPeriodsDetailVO> daoPledgeRewardPeriodsDetailVOList = Lists.newArrayList();
        daoPledgeRewardProduceMap.forEach((key, value) -> {
            Map<Long, Integer> propMap = value.stream().collect(Collectors.groupingBy(DaoPledgeRewardProduce::getPropId, Collectors.summingInt(DaoPledgeRewardProduce::getProductNumber)));
            propMap.forEach((propKey, propValue) -> {
                DaoPledgeRewardPeriodsDetailVO daoPledgeRewardPeriodsDetailVO = new DaoPledgeRewardPeriodsDetailVO();
                daoPledgeRewardPeriodsDetailVO.setBatch(key);
                daoPledgeRewardPeriodsDetailVO.setPropId(propKey);
                daoPledgeRewardPeriodsDetailVO.setPropName(Objects.nonNull(equityPropsMap.get(propKey)) ? equityPropsMap.get(propKey).getFirstTitle() : "");
                daoPledgeRewardPeriodsDetailVO.setProductNumber(propValue);
                daoPledgeRewardPeriodsDetailVOList.add(daoPledgeRewardPeriodsDetailVO);
            });
        });
        return daoPledgeRewardPeriodsDetailVOList;
    }

    @Override
    public IPage<DaoPledgeDirectPushVO> directPushPage(Page page, Long daoId, String targetUserTel, String sourceUserTel) {
        Long targetUserId = null;
        Long sourceUserId = null;
        if (StrUtil.isNotBlank(targetUserTel)) {
            UserInfo userInfo = userInfoDao.getByUserTel(targetUserTel);
            if (Objects.isNull(userInfo)) {
                return page;
            }
            targetUserId = userInfo.getId();
        }
        if (StrUtil.isNotBlank(sourceUserTel)) {
            UserInfo userInfo = userInfoDao.getByUserTel(sourceUserTel);
            if (Objects.isNull(userInfo)) {
                return page;
            }
            sourceUserId = userInfo.getId();
        }
        IPage<DaoPledgeDirectPush> daoPledgeDirectPushIPage = daoPledgeDirectPushDao.page(page, daoId, targetUserId, sourceUserId);
        Set<Long> userIdSet = CollectionUtil.isNotEmpty(daoPledgeDirectPushIPage.getRecords()) ? daoPledgeDirectPushIPage.getRecords().stream().map(DaoPledgeDirectPush::getTargetUserId).distinct().collect(Collectors.toSet()) : Sets.newHashSet();
        userIdSet.addAll(CollectionUtil.isNotEmpty(daoPledgeDirectPushIPage.getRecords()) ? daoPledgeDirectPushIPage.getRecords().stream().map(DaoPledgeDirectPush::getSourceUserId).distinct().collect(Collectors.toSet()) : Sets.newHashSet());
        List<UserInfo> userInfoList = CollectionUtil.isNotEmpty(userIdSet) ? userInfoDao.getByIdList(new ArrayList<>(userIdSet)) : Lists.newArrayList();
        Map<Long, UserInfo> userInfoMap = CollectionUtil.isNotEmpty(userInfoList) ? userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity())) : Maps.newHashMap();
        return daoPledgeDirectPushIPage.convert(v -> {
            DaoPledgeDirectPushVO daoPledgeDirectPushVO = new DaoPledgeDirectPushVO();
            daoPledgeDirectPushVO.setTargetUserId(v.getTargetUserId());
            UserInfo targetUserInfo = userInfoMap.get(v.getTargetUserId());
            daoPledgeDirectPushVO.setTargetUserTel(Objects.nonNull(targetUserInfo) ? DesensitizedUtil.mobilePhone(targetUserInfo.getUserTel()) : "");
            daoPledgeDirectPushVO.setTargetNickName(Objects.nonNull(targetUserInfo) ? targetUserInfo.getNickName() : "");
            daoPledgeDirectPushVO.setSourceUserId(v.getSourceUserId());
            UserInfo sourceUserInfo = userInfoMap.get(v.getSourceUserId());
            daoPledgeDirectPushVO.setSourceUserTel(Objects.nonNull(sourceUserInfo) ? DesensitizedUtil.mobilePhone(sourceUserInfo.getUserTel()) : "");
            daoPledgeDirectPushVO.setSourceNickName(Objects.nonNull(sourceUserInfo) ? sourceUserInfo.getNickName() : "");
            daoPledgeDirectPushVO.setTotalOutCount(v.getTotalOutCount());
            daoPledgeDirectPushVO.setRewardCount(v.getRewardCount());
            daoPledgeDirectPushVO.setGrantTime(v.getGrantTime());
            return daoPledgeDirectPushVO;
        });
    }

    /**
     * 校验新建活动请求参数
     *
     * @param request
     */
    private void validateCreate(DaoPledgeCreateRequest request) {
        Assert.isTrue(request.getStartTime().after(DateTime.now()), () -> new GlobalRunTimeException("开始时间必须晚于当前时间"));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getCollectionIdList()), () -> new GlobalRunTimeException("藏品不能为空"));
        Assert.isTrue(request.getCollectionIdList().size() == (int) request.getCollectionIdList().stream().distinct().count(), () -> new GlobalRunTimeException("藏品不能重复"));

        String filterDaoIds = staticDataDao.getByType("filter_dao_id").getValue();
        JSONArray array = JSONArray.parseArray(filterDaoIds);

        List<DigitalCollection> digitalCollectionList = digitalCollectionDao.getByIds(request.getCollectionIdList());
        Assert.isTrue(CollectionUtil.isNotEmpty(digitalCollectionList) && digitalCollectionList.size() == request.getCollectionIdList().size(), () -> new GlobalRunTimeException("藏品不存在"));
        digitalCollectionList.forEach(digitalCollection -> Assert.isTrue(array.contains(request.getDaoId().longValue()) || Objects.equals(digitalCollection.getUserCreatorId(), request.getDaoId()), () -> new GlobalRunTimeException("藏品与品牌不匹配")));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getPeriodsList()), () -> new GlobalRunTimeException("发行期列表不能为空"));
        IntStream.range(0, request.getPeriodsList().size()).forEach(index -> Assert.isTrue(request.getPeriodsList().get(index).getPeriods() == index + 1, () -> new GlobalRunTimeException("发行期数不正确")));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getProduceList()), () -> new GlobalRunTimeException("产出列表不能为空"));
        IntStream.range(0, request.getProduceList().size()).forEach(index -> Assert.isTrue(request.getProduceList().get(index).getBatch() == index + 1, () -> new GlobalRunTimeException("产出批次不正确")));

        List<Long> propIdList = request.getProduceList().stream().map(DaoPledgeProduceCreateRequest::getPropId).distinct().collect(Collectors.toList());
        List<EquityProps> equityPropsList = equityPropsDao.listByIds(propIdList);
        Assert.isTrue(CollectionUtil.isNotEmpty(equityPropsList) && equityPropsList.size() == propIdList.size(), () -> new GlobalRunTimeException("道具卡不存在"));

    }

    /**
     * 校验新建活动请求参数
     *
     * @param request
     */
    private DaoPledge validateUpdate(DaoPledgeUpdateRequest request) {
        DaoPledge daoPledge = daoPledgeDao.getById(request.getId());
        Assert.notNull(daoPledge, () -> new GlobalRunTimeException("活动不存在"));
        if (!daoPledge.getStatus()) {
            Assert.isTrue(request.getStartTime().after(DateTime.now()), () -> new GlobalRunTimeException("开始时间必须晚于当前时间"));
        }
//        Assert.isFalse(daoPledge.getStatus(), () -> new GlobalRunTimeException("活动已上架，不能修改"));
//        Assert.isTrue(daoPledge.getStartTime().after(DateTime.now()), () -> new GlobalRunTimeException("活动已开始，不能修改"));
        Assert.isTrue(Objects.equals(daoPledge.getDaoId(), request.getDaoId()), () -> new GlobalRunTimeException("活动与品牌不匹配"));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getCollectionIdList()), () -> new GlobalRunTimeException("藏品不能为空"));
        Assert.isTrue(request.getCollectionIdList().size() == (int) request.getCollectionIdList().stream().distinct().count(), () -> new GlobalRunTimeException("藏品不能重复"));

        String filterDaoIds = staticDataDao.getByType("filter_dao_id").getValue();
        JSONArray array = JSONArray.parseArray(filterDaoIds);

        List<DigitalCollection> digitalCollectionList = digitalCollectionDao.getByIds(request.getCollectionIdList());
        Assert.isTrue(CollectionUtil.isNotEmpty(digitalCollectionList) && digitalCollectionList.size() == request.getCollectionIdList().size(), () -> new GlobalRunTimeException("藏品不存在"));
        digitalCollectionList.forEach(digitalCollection -> Assert.isTrue(array.contains(request.getDaoId().longValue()) || Objects.equals(digitalCollection.getUserCreatorId(), request.getDaoId()), () -> new GlobalRunTimeException("藏品与品牌不匹配")));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getPeriodsList()), () -> new GlobalRunTimeException("发行期列表不能为空"));
        IntStream.range(0, request.getPeriodsList().size()).forEach(index -> Assert.isTrue(request.getPeriodsList().get(index).getPeriods() == index + 1, () -> new GlobalRunTimeException("发行期数不正确")));

        Assert.isTrue(CollectionUtil.isNotEmpty(request.getProduceList()), () -> new GlobalRunTimeException("产出列表不能为空"));
        IntStream.range(0, request.getProduceList().size()).forEach(index -> Assert.isTrue(request.getProduceList().get(index).getBatch() == index + 1, () -> new GlobalRunTimeException("产出批次不正确")));

        List<Long> propIdList = request.getProduceList().stream().map(DaoPledgeProduceCreateRequest::getPropId).distinct().collect(Collectors.toList());
        List<EquityProps> equityPropsList = equityPropsDao.listByIds(propIdList);
        Assert.isTrue(CollectionUtil.isNotEmpty(equityPropsList) && equityPropsList.size() == propIdList.size(), () -> new GlobalRunTimeException("道具卡不存在"));
        return daoPledge;
    }

}